﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SGCG.Model;
using System.Reflection;

namespace SGCG.Actions
{
    public abstract class BorderedObjectCreationAction<T> : Action
        where T : GraphicObject, IHasBorder
    {
       private readonly BorderOptions pallete = new BorderOptions();
        private int currentPoint = 1;

        public BorderedObjectCreationAction(PellBitmap pellBitmap) : base(pellBitmap) { }

        public override void HandleClick(MouseButtonEventArgs eventArgs, UIElement plotArea)
        {
            Point clickLocation = eventArgs.GetPosition(plotArea);

            int x = (int)(clickLocation.X + 0.5);
            int y = (int)(clickLocation.Y + 0.5);

            if (BorderedObject == null)
            {
                this.PellBitmap.AddObject(BorderedObject = this.CreateObject(x, y));
                this.currentPoint = 2;
            }
            else
            {
                SetPoint((int)(clickLocation.X + 0.5), (int)(clickLocation.Y + 0.5));

                if (!this.HasMorePoints())
                {
                    this.BorderedObject = null;
                }
                else
                {
                    ++currentPoint;
                }
            }
        }

        public override void HandleMouseMove(MouseEventArgs eventArgs, UIElement plotArea)
        {
            if (BorderedObject != null)
            {
                Point mouseLocation = eventArgs.GetPosition(plotArea);

                SetPoint((int)(mouseLocation.X + 0.5), (int)(mouseLocation.Y + 0.5));
            }
        }

        private void SetPoint(int x, int y)
        {
            using (new BatchRedrawOperation(this.PellBitmap))
            {
                this.SetPointCore(this.currentPoint, x, y);
            }
        }

        protected virtual bool HasMorePoints()
        {
            return this.currentPoint == 1;
        }

        protected abstract T CreateObject(int x, int y);

        protected virtual void SetPointCore(int point, int x, int y)
        {
            PropertyInfo xi = this.BorderedObject.GetType().GetProperty("X" + point, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public);
            PropertyInfo yi = this.BorderedObject.GetType().GetProperty("Y" + point, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public);

            xi.SetValue(this.BorderedObject, x, null);
            yi.SetValue(this.BorderedObject, y, null);
        }

        private T __borderedObject;
        protected T BorderedObject
        {
            get { return __borderedObject; }
            set
            {
                __borderedObject = value;
                pallete.IHasBorder = __borderedObject;
            }
        }

        protected int CurrentPoint
        {
            get { return this.currentPoint; }
        }
        
        public override UIElement Pallete
        {
            get
            {
                return this.pallete;
            }
        }
    }
}
